package org.spring.core.jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.context.annotation.DependsOn;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository(value="jdbcUserDAO")
public class JdbcUserDAOImpl extends JdbcDAO implements JdbcUserDAO{

	protected SimpleJdbcInsert insertUser;
	
	protected static final String USER_TABLE = "SYSTEM_USER";
	
	@PostConstruct
	public void createSimpleJdbcInsert(){
		if(dataSource==null){
			throw new RuntimeException("Datasource cannot be NULL.");
		}
		insertUser = new SimpleJdbcInsert(dataSource).withTableName(USER_TABLE);
	}
	
	public void saveUser(User user) {
		if(user.getId()==null){
			insertUser(user);
		}
	}

	private void insertUser(User user) {
		Map<String, Object> parameters = new HashMap<String, Object>(5);
		if(user.getId()==null){
			Long id = getNextId();
			user.setId(id);
		}
        parameters.put("id", user.getId());        
        parameters.put("first_name", user.getFirstName());
        parameters.put("last_name", user.getLastName());
        parameters.put("birth_date", user.getBirthDate());
        parameters.put("created", user.getCreatedOn());
        insertUser.execute(parameters);	
      }

	private Long getNextId() {
		String sql = "select count(*) from " + USER_TABLE;
		int rowCount = this.jdbcTemplate.queryForInt(sql);
		System.out.println("Found " + rowCount + " user(s).");
		return Integer.valueOf(rowCount).longValue();
	}

	@Override
	public List<User> findAll() {
		String sql = "select * from " + USER_TABLE;
		return this.jdbcTemplate.query(sql,new UserRowMapper());
	}

	@Override
	public void deleteAll() {
		String sql = "delete from " + USER_TABLE;
		this.jdbcTemplate.execute(sql);
	}

	@Override
	public Collection<User> find(User user) {
		String sql = "select * from " + USER_TABLE;
		sql += " where ";
		boolean firstName = false;
		boolean lastName = false;
		Object[] values = new Object[]{};
		if(user.getFirstName()!=null){
			sql += " first_name = ?";
			firstName = true;
			values = new Object[]{
					user.getFirstName()
			};				
		}
		if(user.getLastName()!=null){
			if(user.getFirstName()!=null){
				sql += " and ";
				values = new Object[]{
						user.getFirstName(),
						user.getLastName()
				};				
			}else{
				values = new Object[]{
						user.getLastName()
				};								
			}
			sql += " last_name = ?";
			lastName = true;
		}
		
		
		return this.jdbcTemplate.query(sql, values,new UserRowMapper());
	}
	
	public int[] batchUpdate(List<User> users){
		SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(users.toArray());
        int[] updateCounts = simpleJdbcTemplate.batchUpdate(
            "update "+USER_TABLE+" set first_name = :firstName, last_name = :lastName where id = :id",
            batch);
        return updateCounts;		
	}
	
	private static final class UserRowMapper implements RowMapper<User>{		
		@Override
		public User mapRow(ResultSet rs, int arg1) throws SQLException {
			User u = new User(	rs.getString("first_name"),
					rs.getString("last_name"),
					rs.getDate("birth_date")							
			);
			u.setId(rs.getLong("id"));
			u.setCreatedOn(rs.getDate("created"));
			return u;
		}
		
	}

	@Override
	public void updateAll(List<User> allUsers) {
		batchUpdate(allUsers);
	}
}
